昨天將活動報名以及儲存報名者資訊的功能做好了,而今天要再加上取消報名的功能,以及在頁面顯示當前活動報名人數。
Repository 先前已經完成了刪除報名使用者資料功能了,但還要再新增一個撈取該活動所有 EventsEnroll 的 Function,讓後續可以在 Services 新增一個比對當前使用者的報名資料是否存在於 EventsEnroll 內。
建立以「活動ID」撈取 EventsEnroll 的 Function:
public async Task<IEnumerable<EventsEnroll>> GetEventsEnrollByEventIdAsync(int eventId)
{
var eventsEnrolls = await _appDbContext.EventsEnroll.Where(
ee => ee.Events.Id == eventId
).ToListAsync();
return eventsEnrolls;
}
建立與 GetEventsEnrollByEventIdAsync()
取得的活動比對當前使用者是否被存在於資料內的 Function:
public async Task<bool> IsUserAlreadyEnroll(int id, string userId)
{
try
{
if(id > 0 && !string.IsNullOrEmpty(userId))
{
var eventsEnrolls = await _eventsRepository.GetEventsEnrollsByEventIdAsync(id);
var userInEnroll = eventsEnrolls.Where(
ee => ee.ApplicationUserId == userId
).FirstOrDefault();
if(userInEnroll == null)
{
return false;
}
else
{
return true;
}
}
else
{
throw new Exception("判斷使用者是否在活動報名資料內錯誤。 ID not valid");
}
}
catch (Exception)
{
throw new Exception("判斷使用者是否在活動報名資料內錯誤。");
}
}
修正 EventsEnroll
在判斷是否符合可報名條件(在報名時間內 & 是否已額滿)的邏輯,加入是否已報名:
if (isInEventsSalesTime == true && isApplicationLimitedQtyFull == false
&& !await EventsApplyServices.IsUserAlreadyEnroll((int)id, userId))
{
await _eventsRepository.SaveUserInfoToEventsEnrollAsync(EventsEnroll);
TempData["Message"] = "報名成功";
}
else
{
TempData["Message"] = "報名失敗";
}
public async Task<IActionResult> Details(int? id)
{
if (id == null)
{
return NotFound();
}
var @event = await _eventsRepository.GetEventByIdAsync(id);
if (@event == null)
{
return NotFound();
}
EventsApplyServices EventsApplyServices = new EventsApplyServices(_eventsRepository);
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
if (!await EventsApplyServices.IsApplicationLimitedQtyFull(@event) && EventsApplyServices.IsInEventsSalesTime(@event))
{
if (await EventsApplyServices.IsUserAlreadyEnroll((int)id, userId))
{
ViewData["EnrollBtn"] = 2;
}
else
{
ViewData["EnrollBtn"] = 1;
}
}
else
{
ViewData["EnrollBtn"] = 3;
}
return View(@event);
}
新增 CancelEventsEnroll
取消報名 Action:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> CancelEventsEnroll(int? id)
{
Events Event = new Events();
try
{
if (id != null)
{
Event = await _eventsRepository.GetEventByIdAsync(id);
EventsApplyServices EventsApplyServices = new EventsApplyServices(_eventsRepository);
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
EventsEnroll EventsEnroll = new EventsEnroll()
{
Events = Event,
ApplicationUserId = userId
};
if (Event != null && await EventsApplyServices.IsUserAlreadyEnroll((int)id, userId))
{
await _eventsRepository.DeleteUserInfoFromEventsEnrollAsync(EventsEnroll);
TempData["Message"] = "取消報名成功";
}
else
{
TempData["Message"] = "取消報名失敗";
}
}
else
{
return BadRequest();
}
}
catch (Exception)
{
throw new Exception("取消報名失敗");
}
return RedirectToAction("Details", Event);
}
將報名按鈕加入邏輯,可直接顯示是否允許報名,並將 Form Tag 移到判斷式內,使判斷式可動態切換要使用的 Action:
@{
switch ((int)ViewData["EnrollBtn"])
{
case 1:
<form asp-action="EventsEnroll" method="post" style="display:inline;">
<input type="hidden" asp-for="Id" />
<input type="submit" value="報名" class="btn btn-primary" />
</form>
break;
case 2:
<form asp-action="CancelEventsEnroll" method="post" style="display:inline;">
<input type="submit" value="取消報名" class="btn btn-danger" />
<input type="hidden" asp-for="Id" />
</form>
break;
default:
<input type="button" value="無法報名" class="btn btn-primary" disabled/>
break;
}
}
不在票券販賣時間內時,顯示無法報名:
在票券販賣時間內時且尚未報名,顯示報名:
在票券販賣時間內時且已經報名,顯示取消報名:
今天將取消報名與不在時間內無法報名的邏輯做好了,明天預計會使用一下 Partial View,將提示訊息用 Partial View 的方式來顯示。
也預計將一些按鈕是否顯示的部分做好,例如說只有活動舉辦者才可以顯示編輯按鈕等等的。
那麼我們明天見!